#pragma once

class CResources final :
	public IEngMod
{
public:
	CResources();
	~CResources();

	void ReloadAll();
	void Reload(std::vector<IResource*>& resources);
	void ReloadShaders();

	template<typename T>
	void Add(const std::string& name, T* nresource)
	{
		IResource* test = nresource;

		static uint i = this->m_resourceGeneratorsVec.size();
		static bool initdone = false;

		if (!initdone)
		{
			initdone = true;

			this->m_resourceGeneratorsVec.push_back(new ResourceGenerator<T>());
			AssertLogW(name != "default", "Do not forget to add 'default' item in ResGen<%s>.", typeid(T).name());
		}

		static_cast< ResourceGenerator<T>* >(this->m_resourceGeneratorsVec[i])->Add(name, nresource);
	}

// 	template<typename T>
// 	void Free(const std::string& name)
// 	{
// 		uint size = this->m_resourceGeneratorsVec.size();
// 		ResourceGenerator<T>* ptn = NULL;
//
// 		for (uint i = 0; i < size; ++i)
// 		{
// 			ptn = dynamic_cast<ResourceGenerator<T>*>(this->m_resourceGeneratorsVec[i]);
//
// 			if (ptn)
// 			{
// 				break;
// 			}
// 		}
//
// 		AssertLogC(ptn == NULL, "ResGen<%s>.", );
//
// 		//LogC(!ptn) << "ResourceGenerator< " << std::string(typeid(T).name()) << " > not found";
// 	}

	template<typename T>
	void Get(const std::string& name, T** pointer)
	{
		uint size = this->m_resourceGeneratorsVec.size();
		ResourceGenerator<T>* ptn = NULL;

		for (uint i = 0; i < size; ++i)
		{
			ptn = dynamic_cast<ResourceGenerator<T>*>(this->m_resourceGeneratorsVec[i]);

			if (ptn)
			{
				break;
			}
		}

		AssertLogC(!ptn, "ResGen<%s> not found.", typeid(T).name());

		*pointer = ptn->Get(name);

		if (!*pointer)
		{
			if (name != "default")
			{
				AssertLogE(true, "Not found %s in %s. Trying to load default.", name.c_str(), ptn->GetTypeName().c_str());
				this->Get("default", pointer);
			}
			else
			{
				AssertLogC(true, "Default resource in %s doesn't exist. Returning NULL.", ptn->GetTypeName().c_str());
				*pointer = NULL;

				return;
			}
		}
	}

	void LoadResources(const std::string& file);

private:
	std::vector<IResourceGenerator*> m_resourceGeneratorsVec;
};

namespace sh
{
void reloadshaders();
};

extern CResources* g_Resources;